// /////////////////////////////////////////////////////////////////////////////
//
// Name:            CameraComponent.h
// Author:          Michael Bartsch (ZCCdark203)
//
// Desc :           Declaration of the CameraComponent class.
//
// License:         Copyright (C) 2009 Michael Bartsch and Contributors
//
//                  This program is free software: you can redistribute it
//                  and/or modify it under the terms of the zlib/libpng License.
//                  See main.cpp for conditions of distribution and use.
//
// /////////////////////////////////////////////////////////////////////////////

#ifndef __CAMERACOMPONENT_H__
#define __CAMERACOMPONENT_H__

// Include files
#include "../../dependencies.h"
#include "SceneComponent.h"


// CameraComponent class
//! Component wrapper of Irrlicht's ICameraSceneNode.
//!
//! <b>XML:</b>
//! \code
//! <CameraComponent>
//!    <!-- Properties -->
//! </CameraComponent>
//! \endcode
class CameraComponent : public SceneComponent
{
public:

    // Initialisation and deinitialisation
    //! Constructor (default)
    //! @param parent        The parent entity to which the component should be added.
    //! @param lookat        Position where the camera will look at.
    CameraComponent(Entity *parent, const vector3df &lookat = vector3df(0, 0, 100));
    //! Deconstructor
    ~CameraComponent();

    // Methods
    //! Returns a direct pointer to the ICameraSceneNode.
    //! @note Not available in AngelScript.
    ICameraSceneNode* getCameraSceneNode();

    //! Binds the camera component's rotation to its target position and vice vera, or unbinds them.
    //! bool bound           Value to enable or disable this option.
    void bindTargetAndRotation(bool bound);
    //! Queries if the camera component's rotation and its target position are bound together.
    bool getTargetAndRotationBinding() const;

    //! Gets the aspect ratio of the camera.
    f32 getAspectRatio() const;
    //! Gets the value of the far plane of the camera.
    f32 getFarValue() const;
    //! Gets the field of view of the camera.
    f32 getFOV() const;
    //! Gets the value of the near plane of the camera.
    f32 getNearValue() const;
    //! Gets the current projection matrix of the camera.
    const matrix4& getProjectionMatrix() const;
    //! Gets the current look at target of the camera.
    const vector3df& getTarget() const;
    //! Gets the up vector of the camera.
    const vector3df& getUpVector() const;
    //! Gets the current view matrix of the camera.
    const matrix4& getViewMatrix() const;
    //! Checks if the camera is orthogonal.
    bool getIsOrthogonal() const;

    //! Sets this camera as the main camera.
    //!
    //! <b>XML:</b>
    //! \code
    //! <setAsMainCamera type="bool" value="" />
    //! \endcode
    //!
    void setAsMainCamera();
    //! Sets the aspect ratio (default: 4.0f / 3.0f).
    //!
    //! <b>XML:</b>
    //! \code
    //! <aspectRatio type="number" value="" />
    //! \endcode
    //!
    //! @param aspect        New aspect ratio.
    void setAspectRatio(f32 aspect);
    //! Sets the value of the far clipping plane (default: 2000.0f).
    //!
    //! <b>XML:</b>
    //! \code
    //! <farValue type="number" value="" />
    //! \endcode
    //!
    //! @param value         New far value.
    void setFarValue(f32 value);
    //! Sets the field of view (Default: PI / 2.5f).
    //!
    //! <b>XML:</b>
    //! \code
    //! <FOV type="number" value="" />
    //! \endcode
    //!
    //! @param value         New field of view.
    void setFOV(f32 value);
    //! Sets the value of the near clipping plane. (default: 1.0f).
    //!
    //! <b>XML:</b>
    //! \code
    //! <nearValue type="numnber" value="" />
    //! \endcode
    //!
    //! @param value         New near value.
    void setNearValue(f32 value);
    //! Sets the projection matrix of the camera.
    //! @param projection    The new projection matrix of the camera.
    //! @param isOrthogonal  Set this to true if the matrix is an orthogonal one
    void setProjectionMatrix(const matrix4 &projection, bool isOrthogonal = false);
    //! Sets the rotation of the node.
    //! @param rotation      New rotation in degrees.
    void setRotation(const vector3df &rotation);
    //! Sets the look at target of the camera.
    //!
    //! <b>XML:</b>
    //! \code
    //! <target type="vector3d" value="" />
    //! \endcode
    //!
    //! @param position      New target.
    void setTarget(const vector3df &position);
    //! Sets the up vector of the camera.
    //!
    //! <b>XML:</b>
    //! \code
    //! <upVector type="vector3d" value="" />
    //! \endcode
    //!
    //! @param position      New up vector of the camera.
    void setUpVector(const vector3df &position);

    //! Sets the camera to normal mode.
    void setNormalMode();
    //! Sets the camera to FPS mode.
    //!
    //! <b>XML:</b>
    //! \code
    //! <FPSMode rotateSpeed="" moveSpeed="" verticalMovement="" jumpSpeed=""/>
    //! \endcode
    //!
    //! @param rotateSpeed   Speed in degress with which the camera is rotated.
    //! @param moveSpeed     Speed in units per millisecond with which the camera is moved.
    //! @param verticalMovement Is vertical movement by the camera allowed?
    //! @param jumpSpeed     Speed with which the camera is moved when jumping.
    //! @note Don't forget to call SceneComponent::setCanAffectParent when you switch to this mode.
    void setFPSMode(f32 rotateSpeed = 100.0f, f32 moveSpeed = 0.5f, bool verticalMovement = false,
                    f32 jumpSpeed = 0.0f);
    //! Sets the camera to Maya mode.
    //!
    //! <b>XML:</b>
    //! \code
    //! <MayaMode rotateSpeed="" zoomSpeed="" translationSpeed=""/>
    //! \endcode
    //!
    //! @param rotateSpeed   Rotation speed of the camera.
    //! @param zoomSpeed     Zoom speed of the camera.
    //! @param translationSpeed  Translation speed of the camera.
    //! @note Don't forget to call SceneComponent::setCanAffectParent when you switch to this mode.
    void setMayaMode(f32 rotateSpeed = -1500.0f, f32 zoomSpeed = 200.0f,
                     f32 translationSpeed = 1500.0f);

    // Serialization
    //! Serializes this object.
    //! @param attributes
    virtual bool onSerialization(SerializedAttributes *attributes);
    //! Deserializes this object.
    //! @param attributes
    virtual bool onDeserialization(SerializedAttributes *attributes);

private:

    // Members
    ICameraSceneNode *mCameraSN;
    ISceneNodeAnimator *mCameraAnimator;
};

#endif

